﻿using System;
using System.Linq;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UCL.Powersource;
using UCL.Powersource.Analysis;
using UCL.Powersource.Mock;
using System.Diagnostics;
using PowersourceUIToolkit;
using System.Collections.Generic;

namespace Powersource_UnitTests.StatisticsTest
{
    [TestClass]
    public class StatisticCollectionTests
    {

        //private IReadOnlyDictionary<Guid,IStatistic> st;

        private StatisticTeamBase st1, st3;
        private StatisticCompareTeamsBase st2;
        private IStatisticManager StatisticManager;
        private DummyTeamProjectCollectionConfiguration DummyTPCC;

        private DummyTeamProjectCollectionConfiguration teamProjCollConf;

        //Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize()
        {
            var bs = TestManager.ConfigureNewBootStrapperForTest(TestManager.Configurations.AllDummies,new string[] { "DummyStatistics.dll","BaseStatisticControlLibrary.dll"});
            
            var bd = AppDomain.CurrentDomain.BaseDirectory;
            Trace.WriteLine(string.Format("Basedirectory {0}", bd));
            
            var expPoint = PowersourceConnector.GetExtensibilityPoint();
            StatisticManager = expPoint.StatisticManager;
            DummyTPCC = new DummyTeamProjectCollectionConfiguration();
            st1 = StatisticManager.GetStatisticOrDefault(typeof(DummyStatistic1)) as StatisticTeamBase;
            st2 = StatisticManager.GetStatisticOrDefault(typeof(DummyStatistic2)) as StatisticCompareTeamsBase;
            st3 = StatisticManager.GetStatisticOrDefault(Dummy3Stats) as StatisticTeamBase;
        }
        //
        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            st1 = null; st2 = null; st3 = null;
            teamProjCollConf = null;
            TestManager.DisposeBootStrapper();
        }

        public static Guid Dummy3Stats = new Guid("4E65FDEB-8424-4BD8-83E3-618D585767A0");

        [TestMethod]
        public void TestStatisticComposition()
        {
            Assert.IsNotNull(st1, "Dummy statistics 1 not found");
            Assert.IsNotNull(st2, "Dummy statistics 2 not found");
            Assert.IsNotNull(st3, "Dummy statistics 3 not found");
        }

        [TestMethod]
        public void TestStatisticResolve()
        {
                StatisticManager.ResolveStatistic(st1.GetType(), DummyTPCC);
                StatisticManager.ResolveStatistic(st2.GetType(), DummyTPCC);
                StatisticManager.ResolveStatistic(st3.GetType(), DummyTPCC);

                foreach (var p in DummyTPCC)
            {
                if (p.UniqueName != "TestProject5")
                {
                    Assert.IsTrue(st1.TeamResults.ContainsKey(p),
                                "Entry for {0} not found in {1}.", p.UniqueName, st1.Name);
                    Assert.IsTrue(st2.CompareTeamResults.ContainsKey(p),
                               "Entry for {0} not found in {1}.", p.UniqueName, st2.Name);
                    Assert.IsTrue(st3.TeamResults.ContainsKey(p),
                                "Entry for {0} not found in {1}.", p.UniqueName, st3.Name);

                    foreach (var timeFrame in DummyTPCC.ProjectCollectionTimeFrames)
                    {
                        Assert.IsTrue(st1.TeamResults[p].ContainsKey(timeFrame),
                                    "Entry for {0} not found in statistic {1} for project {2}.", timeFrame.Label, st1.Name, p.UniqueName);
                        Assert.IsTrue(st2.CompareTeamResults[p].ContainsKey(timeFrame),
                                    "Entry for {0} not found in statistic {1} for project {2}.", timeFrame.Label, st2.Name, p.UniqueName);
                        Assert.IsTrue(st3.TeamResults[p].ContainsKey(timeFrame),
                                    "Entry for {0} not found in statistic {1} for project {2}.", timeFrame.Label, st3.Name, p.UniqueName);
                        Assert.IsNotNull(st1.TeamResults[p][timeFrame],
                                    "Value for {0}:{1}:{2} is null.", st1.Name, p.UniqueName, timeFrame.Label);
                        Assert.IsNotNull(st2.CompareTeamResults[p][timeFrame],
                                    "Value for {0}:{1}:{2} is null.", st2.Name, p.UniqueName, timeFrame.Label);
                        Assert.IsNotNull(st3.TeamResults[p][timeFrame].Value,
                                    "Value for {0}:{1}:{2} is null.", st3.Name, p.UniqueName, timeFrame.Label);

                        foreach (var p2 in DummyTPCC)
                        {
                            var teamStat = st2.CompareTeamResults[p][timeFrame].FirstOrDefault(a =>
                                        a.StatTimeFrame == timeFrame && a.TeamProject == p2);

                            if (p2.UniqueName == "TestProject5") 
                                Assert.IsNull(teamStat, "Entry found for non chosen project in {0}", st2.Name);
                            else if (p.UniqueName == p2.UniqueName)
                                Assert.IsNull(teamStat, "Entry found the same project names in {0}", st2.Name);
                            else 
                            {
                                Assert.IsNotNull(teamStat, "No entry for {0}, {1} in {2}", p.UniqueName, p2.UniqueName, st2.Name);
                                Assert.IsNotNull(teamStat.Value, "Value is null for {0}, {1} in {2}", p.UniqueName, p2.UniqueName, st2.Name);
                            }
                        }
                    }
                }
                else
                {
                    Assert.IsFalse(st1.TeamResults.ContainsKey(p), "Entry for {0} not found in {1}.", p.UniqueName, st1.Name);
                    Assert.IsFalse(st2.CompareTeamResults.ContainsKey(p), "Entry for {0} not found in {1}.", p.UniqueName, st2.Name);
                    Assert.IsFalse(st3.TeamResults.ContainsKey(p), "Entry for {0} not found in {1}.", p.UniqueName, st3.Name);
                }
            }
        }
    }
}

